﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AddIn.EA.Framework.Common;

namespace AddIn.EA.Framework
{
    /// <summary>
    /// Class that represent a list of methods. Compose the Element class.
    /// </summary>
    public class MethodList : BaseList<Method>
    {
        #region Constructors
        /// <summary>
        /// Get an instance of methods list
        /// </summary>
        /// <param name="reference">The reference of EA Object Model method</param>
        /// <param name="parent">The parent element</param>
        public MethodList(EA_Application.Collection reference, IElement parent)
            : base(reference, parent) { }
        #endregion
    }

    /// <summary>
    /// Class that represent a method.
    /// </summary>
    public class Method : BaseElement<EA_Application.Method>
    {
        #region Fields
        private MethodTagList _taggedValues;
        private ParameterList _parameters;
        private MethodConditionList _preConditions;
        private MethodConditionList _postConditions;
        #endregion

        #region Constructors
        /// <summary>
        /// Get an instance of method.
        /// </summary>
        /// <param name="reference">The reference of EA Object Model method.</param>
        /// <param name="parent">The parent element.</param>
        public Method(EA_Application.Method reference, IElement parent)
            : base(reference, parent) { }
        #endregion

        #region Properties

        #region BaseElement Members
        /// <summary>
        /// The method id.
        /// </summary>
        public override int ID
        {
            get { return this.Reference.MethodID; }
        }
        /// <summary>
        /// The method name.
        /// </summary>
        public override string Name
        {
            get
            {
                return this.Reference.Name;
            }
            set
            {
                this.Reference.Name = value;
            }
        }
        #endregion
        
        /// <summary>
        /// The method alias. Used to decorate an object with C# standard attribute.
        /// </summary>
        public string Alias
        {
            get { return this.Reference.Style; }
            set { this.Reference.Style = value; }
        }
        /// <summary>
        /// Behavior of the method.
        /// </summary>
        public string Behavior
        {
            get { return this.Reference.Behavior; }
            set { this.Reference.Behavior = value; }
        }
        /// <summary>
        /// Initial Code of the method.
        /// </summary>
        public string Code
        {
            get { return this.Reference.Code; }
            set { this.Reference.Code = value; }
        }
        /// <summary>
        /// Flag used to indicate if the method is static.
        /// </summary>
        public bool IsStatic
        {
            get { return this.Reference.IsStatic; }
            set { this.Reference.IsStatic = value; }
        }
        /// <summary>
        /// Notes for method.
        /// </summary>
        public string Notes
        {
            get { return this.Reference.Notes; }
            set { this.Reference.Notes = value; }
        }
        /// <summary>
        /// The return type of the method.
        /// </summary>
        public string ReturnType
        {
            get { return this.Reference.ReturnType; }
            set { this.Reference.ReturnType = value; }
        }
        /// <summary>
        /// The element scope. Can be Public, Private, Protected or Internal.
        /// </summary>
        public ElementScope Scope
        {
            get
            {
                if (String.IsNullOrEmpty(this.Reference.Visibility))
                    return default(ElementScope);

                try
                {
                    return (ElementScope)Enum.Parse(typeof(ElementScope), this.Reference.Visibility, true);
                }
                catch { return default(ElementScope); }
            }

            set { this.Reference.Visibility = value.ToString(); }
        }
        /// <summary>
        /// The method stereotype.
        /// </summary>
        public string Stereotype
        {
            get { return this.Reference.Stereotype; }
            set { this.Reference.Stereotype = value; }
        }
        /// <summary>
        /// List of tag values for the method. Generally used to indicate values for code generation.
        /// </summary>
        public MethodTagList TaggedValues
        {
            get 
            {
                if (_taggedValues == null)
                    _taggedValues = new MethodTagList(this.Reference.TaggedValues, this);

                return _taggedValues;
            }
        }
        /// <summary>
        /// List of parameter for method.
        /// </summary>
        public ParameterList Parameters
        {
            get
            {
                if (_parameters == null)
                    _parameters = new ParameterList(this.Reference.Parameters, this);

                return _parameters;
            }
        }
        /// <summary>
        /// List of pre-conditions for method.
        /// </summary>
        public MethodConditionList PreConditions
        {
            get
            {
                if (_preConditions == null)
                    _preConditions = new MethodConditionList(this.Reference.PreConditions, this);

                return _preConditions;
            }
        }
        /// <summary>
        /// List of post-conditions for method.
        /// </summary>
        public MethodConditionList PostConditions
        {
            get
            {
                if (_postConditions == null)
                    _postConditions = new MethodConditionList(this.Reference.PostConditions, this);

                return _postConditions;
            }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Get a tag value of the method by tag name.
        /// </summary>
        /// <param name="name">The tag value name.</param>
        /// <returns>The object tag value of the method.</returns>
        public MethodTag GetTaggedValueByName(string name)
        {
            return this.TaggedValues.GetReferenceByName(name);
        }
        /// <summary>
        /// Get a parameter of the method by parameter name.
        /// </summary>
        /// <param name="name">The parameter name.</param>
        /// <returns>The object parameter of the method.</returns>
        public Parameter GetParameterByName(string name)
        {
            return this.Parameters.GetReferenceByName(name);
        }
        #endregion
    }

    /// <summary>
    /// Class that represent a list of method tagged values.
    /// </summary>
    public class MethodTagList : BaseList<MethodTag>
    {
        #region Constructors
        /// <summary>
        /// Get an instance of method tag value.
        /// </summary>
        /// <param name="reference">The reference of EA Object Model method tag value collection.</param>
        /// <param name="parent">The parent element.</param>
        public MethodTagList(EA_Application.Collection reference, IElement parent)
            : base(reference, parent) { }
        #endregion
    }

    /// <summary>
    /// Class that represent a method tag value.
    /// </summary>
    public class MethodTag : BaseElement<EA_Application.MethodTag>
    {
        #region Constructors
        /// <summary>
        /// Get an instance of method tag value.
        /// </summary>
        /// <param name="reference"></param>
        /// <param name="parent"></param>
        public MethodTag(EA_Application.MethodTag reference, IElement parent)
            : base(reference, parent) { }
        #endregion

        #region Properties

        #region BaseElement Members
        /// <summary>
        /// The method tag value id.
        /// </summary>
        public override int ID
        {
            get { return this.Reference.TagID; }
        }
        /// <summary>
        /// The method tag value name.
        /// </summary>
        public override string Name
        {
            get
            {
                return this.Reference.Name;
            }
            set
            {
                this.Reference.Name = value;
            }
        }
        #endregion

        /// <summary>
        /// Notes of the method tag value.
        /// </summary>
        public string Notes
        {
            get { return this.Reference.Notes; }
            set { this.Reference.Notes = value; }
        }

        /// <summary>
        /// The value of method tag.
        /// </summary>
        public string Value
        {
            get { return this.Reference.Value; }
            set { this.Reference.Value = value; }
        }

        #endregion
    }

}
